﻿#region Imports

using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using bGallery.Core.Data;
using bGallery.Core.Domain;
using bGallery.Core.Service;
using Spring.Data.NHibernate.Support;
using Spring.DataBinding;
using IValidator=Spring.Validation.IValidator;
using Page=bGallery.Core.Common.Page;

#endregion

namespace bGallery.Web.Admin
{
	/// <summary>
	/// Category management page
	/// </summary>
	public partial class Categories : Page
	{
		#region Private members

		private ICategoryDao categoryDao;
		private IHierarchicalEnumerable categoryDataSource;
		private IValidator categoryValidator;
		private ICollection checkedNodes;
		private Category selectedCategory;
		private ITextUtil textUtil;

		#endregion

		#region Public properties

		/// <summary>
		/// Gets currently selected category
		/// </summary>
		public Category SelectedCategory
		{
			get { return selectedCategory; }
		}

		/// <summary>
		/// Data source for category tree view
		/// </summary>
		public IHierarchicalEnumerable CategoryDataSource
		{
			set { categoryDataSource = value; }
		}

		/// <summary>
		/// Category data access object
		/// </summary>
		public ICategoryDao CategoryDao
		{
			set { categoryDao = value; }
		}

		/// <summary>
		/// Returns checked nodes in tree
		/// </summary>
		public ICollection CheckedNodes
		{
			set { checkedNodes = value; }
		}

		/// <summary>
		/// Sets validator for category
		/// </summary>
		public IValidator CategoryValidator
		{
			set { categoryValidator = value; }
		}

		/// <summary>
		/// Sets text util
		/// </summary>
		public ITextUtil TextUtil
		{
			set { textUtil = value; }
		}

		#endregion

		#region Event handlers

		protected override void OnInit(EventArgs e)
		{
			if (SignedInUser.Id == 0 || SignedInUser.Username != "admin")
				SetResult("Login");

			base.OnInit(e);
		}

		protected void Page_Load(object sender, EventArgs e)
		{
			InitTree();
			InitParentsDdl();
		}

		/// <summary>
		/// Loads selected category
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void EditCategory(object sender, EventArgs e)
		{
			try
			{
				int id = Convert.ToInt32(((TreeView) sender).SelectedValue);
				selectedCategory = categoryDao.FindById(id);
			}
			catch (Exception ex)
			{
				throw new ArgumentException(GetMessage("error.badTreeSelectedValue"), ex);
			}
		}

		/// <summary>
		/// Saves category
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void Save(object sender, EventArgs e)
		{
			if (Validate(selectedCategory, categoryValidator))
			{
				CheckAbbreviation();
				using (new SessionScope())
				{
					categoryDao.SaveOrUpdate(selectedCategory);
				}
				SetResult("Categories");
			}
		}

		/// <summary>
		/// Deletes selected categories
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void Delete(object sender, EventArgs e)
		{
			foreach (TreeNode node in checkedNodes)
			{
				using (new SessionScope())
				{
					Category cat = categoryDao.FindById(Convert.ToInt32(node.Value));
					if (cat != null)
					{
						categoryDao.Detele(cat);
					}
				}
			}
			SetResult("Categories");
		}

		/// <summary>
		/// Cancels editing category
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void Cancel(object sender, EventArgs e)
		{
			InitializeModel();
		}

		#endregion

		#region Model Management and Data Binding Methods

		/// <summary>
		/// Initializes data model
		/// </summary>
		protected override void InitializeModel()
		{
			selectedCategory = new Category();
			selectedCategory.ParentCategory = new Category();
		}

		/// <summary>
		/// Loads model to page
		/// </summary>
		/// <param name="savedModel"></param>
		protected override void LoadModel(object savedModel)
		{
			selectedCategory = (Category) savedModel;
		}

		/// <summary>
		/// Saves model from page
		/// </summary>
		/// <returns></returns>
		protected override object SaveModel()
		{
			return selectedCategory;
		}

		/// <summary>
		/// Initializes data bindings
		/// </summary>
		protected override void InitializeDataBindings()
		{
			BindingManager.AddBinding("tbName.Text", "SelectedCategory.Name");
			BindingManager.AddBinding("tbAbbreviation.Text", "SelectedCategory.Abbreviation", BindingDirection.TargetToSource);
			BindingManager.AddBinding("tbDescription.Text", "SelectedCategory.Description");

			BindingManager.AddBinding("@(CategoryDao).FindById(ddlParent.SelectedValue)", "SelectedCategory.ParentCategory",
			                          BindingDirection.SourceToTarget);
			BindingManager.AddBinding("ddlParent.SelectedValue", "SelectedCategory.ParentId.ToString()",
			                          BindingDirection.TargetToSource);

			BindingManager.AddBinding("tvCategories.CheckedNodes", "CheckedNodes", BindingDirection.SourceToTarget);
		}

		#endregion

		#region Private methods

		/// <summary>
		/// Initializes grid
		/// </summary>
		private void InitTree()
		{
			if (!IsPostBack)
			{
				tvCategories.DataSource = categoryDataSource;
				tvCategories.DataBind();
			}
		}

		/// <summary>
		/// Inits parent categories dropdown list
		/// </summary>
		private void InitParentsDdl()
		{
			IList<Category> cats = categoryDao.FindAll();
			cats.Insert(0, new Category(0, string.Empty, string.Empty));
			ddlParent.DataSource = cats;
			ddlParent.DataBind();
		}

		/// <summary>
		/// Checks if the abbreviation is unique and in
		/// other case makes it unique
		/// </summary>
		private void CheckAbbreviation()
		{
			selectedCategory.Abbreviation = textUtil.GetUrlFriendlyName(selectedCategory.Name);
			string newAbbreviation = selectedCategory.Abbreviation;
			int level = 1;

			while (!categoryDao.IsUnique(newAbbreviation, selectedCategory.Id))
			{
				newAbbreviation = selectedCategory.Abbreviation + level++;
			}

			selectedCategory.Abbreviation = newAbbreviation;
		}

		#endregion
	}
}